/**
 * Created on [2021/1/22 20:17] by 刘金龙
 * <p>
 * 项目名称: orion
 * <p>
 * 本程序版权属于福建慧政通信息科技有限公司所有。
 * 任何组织和个人未经福建慧政通信息科技有限公司许可与授权,不得擅自传播、复制、更改该程序的内容。
 * 本程序受版权法和国际条约的保护。如未经授权而擅自复制或传播本程序(或其中任何部分),
 * 将受到严厉的刑事及民事制裁，并将在法律许可的范围内受到最大可能的起诉!
 * <p>
 * ©2021 福建慧政通信息科技有限公司
 */
package com.sunnada.btfvilg.common.exception;


import com.sunnada.btfvilg.common.response.ResponseStatusCode;
import com.sunnada.btfvilg.common.response.Result;
import com.sunnada.btfvilg.common.response.ResultFactory;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * 全局异常捕获
 *
 * @author 刘金龙
 * @since 2021/1/22
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(ConstraintViolationException.class)
    public Result handleError(ConstraintViolationException e) {
        StringBuilder message = new StringBuilder();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            String path = ((PathImpl) constraintViolation.getPropertyPath()).getLeafNode().getName();
            message.append(String.format("%s:%s；", path, constraintViolation.getMessage()));
        }
        log.error("ConstraintViolationException->", e);
        return ResultFactory.create(ResponseStatusCode.INVALID_ARGUMENT.getCode(), message.toString(), null);
    }

    @ExceptionHandler(BindException.class)
    public Result handleError(BindException e) {
        //参数bing异常
        List<FieldError> fieldErrors = e.getFieldErrors();
        StringBuffer message = new StringBuffer();
        for (FieldError fieldError : fieldErrors) {
            message.append(fieldError.getDefaultMessage());
            message.append(";");
        }
        return ResultFactory.create(ResponseStatusCode.INVALID_ARGUMENT.getCode(), message.toString(), null);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result handleError(MissingServletRequestParameterException e) {
        log.error("MissingServletRequestParameterException->", e);
        return ResultFactory.create(ResponseStatusCode.INVALID_ARGUMENT.getCode(), "必填参数未提交:" + e.getMessage(), null);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleError(MethodArgumentNotValidException e) {
        //参数bing异常
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        StringBuffer message = new StringBuffer();
        for (FieldError fieldError : fieldErrors) {
            message.append(fieldError.getDefaultMessage());
            message.append(";");
        }
        return ResultFactory.create(ResponseStatusCode.INVALID_ARGUMENT.getCode(), message.toString(), null);
    }

    @ExceptionHandler(value = {ServiceException.class})
    public Result handleError(ServiceException e) {
        log.error("ServiceException -> ",e);
        return ResultFactory.create(e.getResponseStatusCode().getCode(), e.getMessage(), null);
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Result handleError(MaxUploadSizeExceededException e) {
        log.error("MaxUploadSizeExceededException ->", e);
        return ResultFactory.create(ResponseStatusCode.INVALID_ARGUMENT.getCode(), "您的材料大小超出规定，无法上传", null);
    }

    /*对请求方式错误进行输出*/
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handleError(HttpRequestMethodNotSupportedException e) {
        return ResultFactory.create(ResponseStatusCode.INCORRECT_FORMAT.getCode(), "接口请求方式错误,请确认接口正确的请求方式如：post,get,put,delete等等", null);
    }

    /*对参数类型错误进行输出*/
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Result handleError(MethodArgumentTypeMismatchException e) {
        return ResultFactory.create(ResponseStatusCode.INCORRECT_FORMAT.getCode(), "参数类型错误,请检查参数：" + e.getMessage(), null);
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Result handleError(HttpMediaTypeNotSupportedException e) {
        return ResultFactory.create(ResponseStatusCode.INCORRECT_FORMAT.getCode(), "参数的提交形式错误，请确认提交的数据形式，例如后端接收的是json，前端提交却是application/x-www-form-urlencoded。" + e.getMessage(), null);
    }

    @ExceptionHandler(Throwable.class)
    public Result handleError(Throwable e) {
        log.error("Throwable", e);
        return ResultFactory.create(ResponseStatusCode.INVALID_SERVER_REQUEST.getCode(), ResponseStatusCode.INVALID_SERVER_REQUEST.getMessage(), null);
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public Result handleError(IllegalArgumentException e) {
        return ResultFactory.create(ResponseStatusCode.INVALID_ARGUMENT.getCode(), e.getMessage(), null);
    }

}